package com.terry.web.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.terry.web.config.filter.RestAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Map;

/**
 * Date：2021/8/28
 * Time：14:12
 * Description：SecurityConfig
 *
 * @author Terry
 * @version 1.0
 */
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests(req -> req
                .antMatchers("/authorize/**").permitAll()
                .antMatchers("/test").permitAll()
                .antMatchers("/hello").authenticated()
                .anyRequest().authenticated()

        )
           .addFilterAt(restAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
//            .formLogin(form -> form
//                    .successHandler(jsonAuthenticationSuccessHandler())
//                    .failureHandler(getAuthenticationFailureHandler())
//                    .permitAll()
//
//            )
//            .httpBasic(Customizer.withDefaults())
            .csrf(csrf -> csrf.disable());
    }

    private AuthenticationFailureHandler getAuthenticationFailureHandler() {
        return (req,res,exp) -> {
            res.setStatus(HttpStatus.UNAUTHORIZED.value());
            res.setContentType(MediaType.APPLICATION_JSON_VALUE);
            res.setCharacterEncoding("UTF-8");
            val error = Map.of("title", "认证失败",
                    "details", exp.getMessage()
            );
            res.getWriter().println(objectMapper.writeValueAsString(error));


        };
    }


    private RestAuthenticationFilter restAuthenticationFilter() throws Exception{
        RestAuthenticationFilter filter = new RestAuthenticationFilter(objectMapper);

        filter.setAuthenticationFailureHandler(getAuthenticationFailureHandler());
        filter.setAuthenticationSuccessHandler(jsonAuthenticationSuccessHandler());
        filter.setAuthenticationManager(authenticationManager());
        filter.setFilterProcessesUrl("/authorize/login");
        return filter;
    }


    private AuthenticationSuccessHandler jsonAuthenticationSuccessHandler(){
        return (req,res,auth) ->{
          res.setStatus(HttpStatus.OK.value());
          res.getWriter().println(objectMapper.writeValueAsString(auth));
        };
    }

//    /**
//     * BCrypt密码编码
//     */
//    @Bean("passwordEncoder")
//    public PasswordEncoder passwordEncoder() {
//        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
//    }



    //配置真正路径的安全性过滤链
    @Override
    public void configure(WebSecurity web) throws Exception {
        //public 路径，不启用安全过滤器链。（静态文件）
        web.ignoring().mvcMatchers("/public/**");
    }



    //    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http.authorizeRequests()
//                .antMatchers("/api/**").hasRole("USER")
//                .anyRequest().authenticated()
//
//                // 重新返回一个httpSecurity
//                .and()
//                .formLogin().loginPage("/login").usernameParameter("username1")
//                .and()
//                .httpBasic().realmName("BA");
//    }

}
